﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using GameLogic.Controls;
using Microsoft.Devices.Sensors;

namespace PilotOS
{
    public partial class PilotOSGame : UserControl, IGameFeatures
    {
        public PilotOSGame()
        {
            InitializeComponent();

            if (DesignerProperties.IsInDesignTool)
            {
                return;
            }

            _timer = new DispatcherTimer();
            _timer.Tick += (s, e) =>
                {
                    DoGameStep();
                };

            _transformGroup = new TransformGroup();

            _rotate = new RotateTransform();
            _transformGroup.Children.Add(_rotate);

            _translate = new TranslateTransform();
            _transformGroup.Children.Add(_translate);

            _ground.RenderTransform = _transformGroup;

            _acc = new Accelerometer();
            _acc.ReadingChanged += new EventHandler<AccelerometerReadingEventArgs>(_acc_ReadingChanged);

            _plane.Landed += new EventHandler(_plane_Landed);
        }

        void _plane_Landed(object sender, EventArgs e)
        {
            CheckGameOver();
        }

        private void CheckGameOver()
        {
            // Correct Angle
            bool correctAngle = false;

            // Correct Area
            bool correctArea = false;

            if (correctAngle && correctArea)
            {

            }
            else
            {
                // Crashed
                OnGameOver();   
            }
        }

        double _rotatefactor = 1.0;

        double _currentSpeed = 200.0;
        double _defaultX;
        double _defaultY;
        double _defaultZ;

        double _defaultNavigationStep = 5;

        TransformGroup _transformGroup;
        RotateTransform _rotate;
        TranslateTransform _translate;

        Accelerometer _acc;
        DispatcherTimer _timer;

        int _tickRate = 10;
        double _speedRate = 1;

        Rect _landingRect;
        Point _currentPosition;

        #region Sensor Logic / Events

        void _acc_ReadingChanged(object sender, AccelerometerReadingEventArgs e)
        {
            Dispatcher.BeginInvoke(() =>
                {
                    if (_defaultX == 0 && _defaultY == 0 && _defaultZ == 0)
                    {
                        _defaultX = e.X;
                        _defaultY = e.Y;
                        _defaultZ = e.Z;
                    }

                    Navigate(e.X - _defaultX, e.Y - _defaultY, e.Z - _defaultZ);
                });
        }

        #endregion



        public void OnScoresChanged(int scores)
        {
        }

        public void OnLivesChanged(int lives)
        {
        }

        private void Navigate(double x, double y, double z)
        {
            UpdateRotationCenter();

            _accX.Text = x.ToString();
            _accY.Text = y.ToString();
            _accZ.Text = z.ToString();

            // Rotate
            _rotate.CenterX = this.ActualWidth / 2;
            _rotate.CenterY = this.ActualHeight/ 2;
            _rotate.Angle -= x;
            while (_rotate.Angle < 0)
            {
                _rotate.Angle += 360;
            }

            while (_rotate.Angle > 359)
            {
                _rotate.Angle -= 360;
            }
            _angle.Text = _rotate.Angle.ToString();

            // Altitude
            _plane.Altitude -= y;
        }
        
        private void DoGameStep()
        {
            //_translate.Y += _speedRate;

            //_landingRect = new Rect(_landingArea.Margin.Left, _landingArea.Margin.Top,
            //    _landingArea.ActualWidth, ActualHeight);

            
            //_angle.Text = _rotate.Angle.ToString();

            //// Update current position
            //_speed.Text = _currentSpeed.ToString();
            //double speed = _currentSpeed / (1000 / _tickRate);
            //_currentPosition = CalcMove(_currentPosition, _rotate.Angle, speed);
            
            //Point center = GetCenterOfGround();

            //_centerX.Text = center.X.ToString();
            //_centerY.Text = center.Y.ToString();

            //_landingAreaCoords.Text = "X1: " + _landingRect.Left + " Y1: " + _landingRect.Top
            //    + " X2: " + _landingRect.Right + " Y2: " + _landingRect.Bottom;

            //if (_landingRect.Left < center.X && _landingRect.Right > center.X &&
            //    _landingRect.Top < center.Y && _landingRect.Bottom > center.Y)
            //{
            //    // In Landing Area

            //    if (_plane.Altitude < 1)
            //    {
            //        // Correct Altitude
            //        if (_rotate.Angle < 20 || _rotate.Angle > 340)
            //        {
            //            // Correct Landing Angle
            //            OnGameOver()
            //        }
            //    }
            //}

            //if (_plane.Altitude < 0)
            //{
            //    // Crashed 
            //    GameOve(this, EventArgs.Empty);
            //}
        }

        private void OnGameOver()
        {
            if (GameOver != null)
            {
                GameOverEventArgs args = new GameOverEventArgs();
                GameOver(this, args);
            }
        }

        Point CalcMove(Point pt, double angle, double speed) 
        { 
            Point ret = pt; 
            //ret.X = (int)(ret.X + speed * Math.Sin(DegToRad(angle))); 
            //ret.Y = (int)(ret.Y + speed * Math.Cos(DegToRad(angle))); 
            ret.X = (int)(ret.X + speed * Math.Sin(angle));
            ret.Y = (int)(ret.Y + speed * Math.Cos(angle)); 
            return ret; 
        }

        
        private Point GetCenterOfGround()
        {
            //Point p = new Point();
            //p.X = (_ground.ActualWidth - _translate.X) / 2;
            //p.Y = (_ground.ActualHeight - _translate.Y) / 2;

            Point p = _currentPosition;

            return p;
        }

        private void UpdateRotationCenter()
        {
            Point center = GetCenterOfGround();

            _rotate.CenterX = center.X;
            _rotate.CenterY = center.Y;
        }

        #region Controls for emulator

        private void _down_Click(object sender, RoutedEventArgs e)
        {
            Navigate(0, +_defaultNavigationStep, 0);
        }

        private void _up_Click(object sender, RoutedEventArgs e)
        {
            Navigate(0, -_defaultNavigationStep, 0);
        }

        private void _right_Click(object sender, RoutedEventArgs e)
        {
            Navigate(_defaultNavigationStep, 0, 0);
        }

        private void _left_Click(object sender, RoutedEventArgs e)
        {
            Navigate(-_defaultNavigationStep, 0, 0);
        }

        #endregion

        #region IGameFeatures

        public void Start()
        {
            _timer.Interval = new TimeSpan(0, 0, 0, 0, _tickRate);
            _timer.Start();

            _currentPosition = new Point();

            _acc.Start();
        }

        public void Stop()
        {
            _acc.Stop();
            _timer.Stop();
        }

        public void Pause()
        {
            _acc.Stop();
            _timer.Stop();
        }

        public void Resume()
        {
            _timer.Start();
            _acc.Start();
        }


        public bool IsTimeBased
        {
            get { return false; }
        }

        public bool IsLifeBased
        {
            get { return true; }
        }

        public string GameName
        {
            get { return "Pilotos"; }
        }

        public event EventHandler<ScoresChangedEventArgs> ScoresChanged;
        public event EventHandler<LivesChangedEventArgs> LivesChanged;

        public void ChangeScores(int value)
        {

        }

        public void ChangeLives(int value)
        {

        }

        #endregion

        public TimeSpan GameDuration
        {
            get { throw new NotImplementedException(); }
        }

        public string DeveloperName
        {
            get { return "Oliver Scheer"; }
        }

        public string CompanyName
        {
            get { return "os75.com"; }
        }

        public string Description
        {
            get { return string.Empty; }
        }

        public event EventHandler<GameOverEventArgs> GameOver;
        public event EventHandler<TimeChangedEventArgs> TimeChanged;

        public Uri SettingsPage
        {
            get { return null; }
        }


    }
}